﻿/*
 * Autore: Paolo Farina
 */

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using RecipesManager.Data;
using RecipesManager.Data.Operations;
using MessageBox = System.Windows.MessageBox;

namespace RecipesManager.MainControls.EventSubControls
{

    public class MenuElems
    {
        public MenuElems(string name, int portions)
        {
            NAME = name;
            if (portions <= 0) PORTIONS = 1;
            else PORTIONS = portions;
        }

        public string NAME { get; set; }
        public int PORTIONS { get; set; }

        // override object.Equals
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            if (((MenuElems)obj).NAME.Equals(this.NAME))
                return true;
            return false;

        }



        //TODO mi sembra che questo non sia un metodo corretto per calcolare il hashcode.. da confermare
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }

    public class GuestElems
    {
        public GuestElems(string name, bool haspart)
        {
            NAME = name;
            if(haspart) HASPART = "Partecipanti";
            else HASPART = "Assenti";

        }

        public string NAME { get; set; }
        public string HASPART { get; set; }

        // override object.Equals
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            if (((GuestElems)obj).NAME.Equals(this.NAME))
                return true;
            return false;

        }



        //TODO mi sembra che questo non sia un metodo corretto per calcolare il hashcode.. da confermare
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }

    /// <summary>
    /// Logica di interazione per EventMainPane.xaml
    /// </summary>
    public partial class EventMainPane : UserControl
    {
        public IEvent _event=null;
        bool _editing = false;
        Dictionary<string, bool> opLogGuest;
        Dictionary<MenuElems, bool> opLogRecip;
        ObservableCollection<MenuElems> menuElems = new ObservableCollection<MenuElems>();
        ObservableCollection<GuestElems> guestElems = new ObservableCollection<GuestElems>();
        ICollectionView cbGuestView;
        ICollectionView cbMenuView;
        Classifier cls=null;
        


        public EventMainPane(string name, int id)
        {
            InitializeComponent();

            if (name != null && !name.Equals(""))
            {
                
                var ev = Manager.Events[id];
                _event = ev;
                this.tb_nomeEvento.Text = _event.Name;
                _editing = true;
                if (!_event.Date.GetValueOrDefault().Equals(new DateTime())) dp_dataEvento.Value = _event.Date.GetValueOrDefault();
                rtb_notes.Text = _event.Notes;
                
               
                guestElems=new ObservableCollection<GuestElems>();

                cls = new Classifier(_event.Guests.Select(gp => gp.Guest), _event.Recipes.Select(rc => rc.Recipe));

                foreach (var guest in _event.Guests)
                {
                    guestElems.Add(new GuestElems(guest.Name,guest.HasParticipated));
                }
 
                menuElems = new ObservableCollection<MenuElems>();

                foreach (var recipe in _event.Recipes) menuElems.Add(new MenuElems(recipe.Name, recipe.Servings.GetValueOrDefault()));

                if (ev.HasEnded)
                {
                    tb_closeEvent.IsChecked = true;
                    tb_closeEvent.IsEnabled = false;
                    UpdateInterfaceEventEnded();
                }
            }
            else
            {
              
                cls = new Classifier(new List<IGuest>(), new List<IRecipe>());
            }
            
            

            bt_salva.IsEnabled = false;
            bt_cancGuest.IsEnabled = false;
            bt_addGuest.IsEnabled = false;
            bt_cancMenu.IsEnabled = false;
            bt_addMenu.IsEnabled = false;
            bt_viewMenu.IsEnabled = false;
            bt_printMenu.IsEnabled = false;
            bt_addRtSL.IsEnabled = false;
            bt_delRtSL.IsEnabled = false;

            opLogGuest = new Dictionary<string, bool>();
            opLogRecip = new Dictionary<MenuElems, bool>();

            cb_invitati.IsEditable = true;
            cb_ricette.IsEditable = true;


            
            
            cbGuestView = CollectionViewSource.GetDefaultView(cls.RatedGuests);
            cbGuestView.GroupDescriptions.Add(new PropertyGroupDescription("TypeDescription"));
            cbGuestView.SortDescriptions.Add(new SortDescription("Type", ListSortDirection.Ascending));
            cbGuestView.SortDescriptions.Add(new SortDescription("Guest.Name", ListSortDirection.Ascending));

            cbMenuView = CollectionViewSource.GetDefaultView(cls.RatedRecipes);
            cbMenuView.GroupDescriptions.Add(new PropertyGroupDescription("TypeDescription"));
            cbMenuView.SortDescriptions.Add(new SortDescription("Rating", ListSortDirection.Descending));
            cbMenuView.SortDescriptions.Add(new SortDescription("Recipe.Name", ListSortDirection.Ascending));
            
            UpdateInteface(name, id);
        }

        internal void UpdateInteface(string name, int id)
        {

            lb_menuRicette.ItemsSource = menuElems;
           
            cbGuestView = CollectionViewSource.GetDefaultView(cls.RatedGuests);
            cbMenuView = CollectionViewSource.GetDefaultView(cls.RatedRecipes);

            lb_invitati.ItemsSource = guestElems;
            cb_invitati.ItemsSource = cbGuestView;
            cb_ricette.ItemsSource = cbMenuView;
            lb_conflitti.ItemsSource = cls.Issues;

            if(dp_dataEvento.Value==null && !_editing) dp_dataEvento.Value=DateTime.Now;
            

            cbGuestView.Refresh();
            cbMenuView.Refresh();
        }

        public bool Save()
        {
            try
            {
                IEvent ev = null;
                bool evStat = false;

                if (_editing) ev = Manager.Events[_event.Id];
                

               if ((ev==null || !ev.HasEnded) && tb_closeEvent.IsChecked.GetValueOrDefault())
               {
                   
                   var result = MessageBox.Show((string)Application.Current.FindResource("AlertClosingEvent"), "Avviso", MessageBoxButton.YesNo,
                                MessageBoxImage.Exclamation);
                   switch (result)
                   {
                       case MessageBoxResult.Yes:
                           break;
                       case MessageBoxResult.No:
                           tb_closeEvent.IsChecked = false;
                           return false;                       
                   }
                   if (ev == null) ev = Manager.Events.Add(tb_nomeEvento.Text);
                   evStat = true;
               }

               if (ev == null) ev = Manager.Events.Add(tb_nomeEvento.Text);

               bt_salva.IsEnabled = false;

               ev.Update(tb_nomeEvento.Text, rtb_notes.Text, dp_dataEvento.Value);
               
                foreach (var log in opLogGuest)
                {
                    if (log.Value) ev.Guests.Add(log.Key);
                    else ev.Guests.Remove(log.Key);
                }

                foreach (var log in opLogRecip)
                {
                    if (log.Value) ev.Recipes.Add(log.Key.NAME, log.Key.PORTIONS);
                    else ev.Recipes.Remove(log.Key.NAME);
                }

                foreach (var menuElemse in menuElems)
                {
                    if(ev.Recipes[menuElemse.NAME].Servings.GetValueOrDefault()!=menuElemse.PORTIONS)ev.Recipes[menuElemse.NAME].Update(menuElemse.PORTIONS);
                }
                
                foreach (var guestElemse in guestElems)
                {
                    var tmp = guestElemse.HASPART.Equals("Partecipanti");
                    if (ev.Guests[guestElemse.NAME].HasParticipated != tmp) ev.Guests[guestElemse.NAME].Update(tmp);
                }

                opLogGuest.Clear();
                opLogRecip.Clear();

                _editing = true;
                _event = ev;

                if(evStat)
                {
                    Data.Operations.Operations.RegisterStats(ev);
                    UpdateInterfaceEventEnded();
                }

            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Avviso", MessageBoxButton.OK,
                                MessageBoxImage.Error);

                if (tb_nomeEvento.IsEnabled && tb_closeEvent.IsChecked.GetValueOrDefault())
                    tb_closeEvent.IsChecked = false;

                return false;
            }



            UpdateInteface(tb_nomeEvento.Text, _event == null ? 0 : _event.Id);
            return true;
            
        }

        private bool Is_Modified(int ctrl)
        {
           
           if (_event == null) return true;
           if (ctrl == 0) return true;
           if (_event != null && !_event.Notes.Equals(rtb_notes.Text)) return true;
           if (_event != null && !_event.Date.Equals(dp_dataEvento.Value)) return true;
           if ((opLogGuest!=null && opLogGuest.Count > 0) || (opLogRecip!=null && opLogRecip.Count > 0)) return true;
           foreach (var menuElemse in menuElems)
           {
               if (_event.Recipes[menuElemse.NAME].Servings.GetValueOrDefault() != menuElemse.PORTIONS)
                            return true;
           }     
           return false;
        }


        #region ButtonHandler

        void Tb_RicetteInvitati_TextChanged(object sender, TextChangedEventArgs e)
        {
            var tbsource = (ComboBox) sender;
            UpdateInteface(tb_nomeEvento.Text, _event==null ? 0 : _event.Id);
            if (tbsource.Name.EndsWith("invitati"))
            {
                if (cls.RatedGuests.Contains(cb_invitati.SelectedValue)) bt_addGuest.IsEnabled = true;
                else bt_addGuest.IsEnabled = false;
                cb_invitati.IsDropDownOpen = true;
            }
            else
            {
                if (cls.RatedRecipes.Contains(cb_ricette.SelectedValue)) bt_addMenu.IsEnabled = true;
                else bt_addMenu.IsEnabled = false;
                cb_ricette.IsDropDownOpen = true;
            }
        }

        void Tb_NomeEvento_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (!Is_Modified(0)) bt_salva.IsEnabled = false;
            else bt_salva.IsEnabled = true;
        }

        void RTb_NoteEvento_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (!Is_Modified(1)) bt_salva.IsEnabled = false;
            else bt_salva.IsEnabled = true;
        }


        private void Dp_DataEvento_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (!Is_Modified(2)) bt_salva.IsEnabled = false;
            else bt_salva.IsEnabled = true;
        }

        void Agg_Button_Click(object sender, RoutedEventArgs e)
        {
            if (((Button)sender).Name.EndsWith("Guest"))
            {
                var invitati = new GuestElems(((RatedGuest)cb_invitati.SelectedValue).Guest.Name, true); ;
                if (!opLogGuest.ContainsKey(invitati.NAME)) opLogGuest.Add(invitati.NAME, true);
                guestElems.Insert(0, invitati);
                cls.OnGuestAdd(invitati.NAME);
                cb_invitati.IsDropDownOpen = false;
                cb_ricette.IsDropDownOpen = false;
                bt_addGuest.IsEnabled = false;
                if (!Is_Modified(3)) bt_salva.IsEnabled = false;
                else bt_salva.IsEnabled = true;
            }
            else
            {
                var tmpRec=((RatedRecipe) cb_ricette.SelectedValue).Recipe;
                var ricetta = new MenuElems(tmpRec.Name, Manager.Recipes[tmpRec.Name].Servings.GetValueOrDefault());
                if (!opLogRecip.ContainsKey(ricetta)) opLogRecip.Add(ricetta, true);
                menuElems.Insert(0, ricetta);
                bt_addMenu.IsEnabled = false;                
                cls.OnRecipeAdd(ricetta.NAME);               
                cb_ricette.IsDropDownOpen = false;

                if (!Is_Modified(4)) bt_salva.IsEnabled = false;
                else bt_salva.IsEnabled = true;
            }
            

            UpdateInteface(tb_nomeEvento.Text, _event==null ? 0 : _event.Id);


        }

        void Canc_Button_Click(object sender, RoutedEventArgs e)
        {
            if (((Button)sender).Name.EndsWith("Guest"))
            {
                var invitati = (GuestElems) lb_invitati.SelectedItem;
                if (!opLogGuest.ContainsKey(invitati.NAME)) opLogGuest.Add(invitati.NAME, false);
                else opLogGuest.Remove(invitati.NAME);
                guestElems.Remove(invitati);
                cls.OnGuestRemove(invitati.NAME);
                cb_invitati.IsDropDownOpen = false;
                cb_ricette.IsDropDownOpen = false;
                if (!Is_Modified(3)) bt_salva.IsEnabled = false;
                else bt_salva.IsEnabled = true;
            }
            else
            {
                var ricetta=(MenuElems)lb_menuRicette.SelectedItem;
                if (!opLogRecip.ContainsKey(ricetta)) opLogRecip.Add(ricetta, false);
                else opLogRecip.Remove(ricetta);
                menuElems.Remove(ricetta);
                cls.OnRecipeRemove(ricetta.NAME);
                cb_ricette.IsDropDownOpen = false;
                if (!Is_Modified(4)) bt_salva.IsEnabled = false;
                else bt_salva.IsEnabled = true;
            }


            UpdateInteface(tb_nomeEvento.Text, _event == null ? 0 : _event.Id);

        }

        void AggDelRecipetSl_Button_Click(object sender, RoutedEventArgs e)
        {
            Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
            var bt = (Button) sender;
            IEnumerable<string> mex;

            if(lb_menuRicette.SelectedItem==null)MessageBox.Show("Seleziona prima una ricetta...", "Avviso", MessageBoxButton.OK, MessageBoxImage.Information);
            var selElem = (MenuElems) lb_menuRicette.SelectedValue;

            if(bt.Name.Equals("bt_addRtSL"))  mex=Data.Operations.Operations.AddRecipeToShoppingList(selElem.NAME, selElem.PORTIONS);
            else  mex = Data.Operations.Operations.RemoveRecipeFromShoppingList(selElem.NAME, selElem.PORTIONS);

            if(mex.Any())
            {
                var msgFromCanRemove = mex.Aggregate("", (current, m) => current + (Environment.NewLine + m));
                MessageBox.Show("Operazione Eseguita, ma ci sono stati dei problemi: " + msgFromCanRemove, "Avviso", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            else MessageBox.Show("Operazione Eseguita", "Avviso", MessageBoxButton.OK, MessageBoxImage.Information);
            Mouse.OverrideCursor = null;
        }

        void AggAllRecipetSl_Button_Click(object sender, RoutedEventArgs e)
        {
            Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
            var rec=new List<string>();
            var por = new List<int?>();

            foreach (var menuElemse in menuElems)
            {
                rec.Add(menuElemse.NAME);
                por.Add(menuElemse.PORTIONS);
            }

            var mex = Data.Operations.Operations.AddMenuToShoppingList(rec, por);

            if (mex.Any())
            {
                var msgFromCanRemove = mex.Aggregate("", (current, m) => current + (Environment.NewLine + m));
                MessageBox.Show("Operazione Eseguita, ma ci sono stati dei problemi: " + msgFromCanRemove, "Avviso", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            else MessageBox.Show("Operazione Eseguita", "Avviso", MessageBoxButton.OK, MessageBoxImage.Information);
            Mouse.OverrideCursor = null;
        }




        void Grid_Inv_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            bt_cancGuest.IsEnabled = lb_invitati.SelectedItem != null;
        }

        void Grid_Ev_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

                if (lb_menuRicette.SelectedItem == null)
                {
                    bt_cancMenu.IsEnabled = false;
                    bt_addRtSL.IsEnabled = false;
                    bt_delRtSL.IsEnabled = false;
                }
                else
                {
                    bt_cancMenu.IsEnabled = true;
                    bt_addRtSL.IsEnabled = true;
                    bt_delRtSL.IsEnabled = true;
                }
        }

        private void UpdateInterfaceEventEnded()
        {
            bt_addGuest.IsEnabled = false;
            bt_cancGuest.IsEnabled = false;
            bt_addMenu.IsEnabled = false;
            bt_cancMenu.IsEnabled = false;            
            rtb_notes.IsEnabled = true;
            dp_dataEvento.IsEnabled = false;
            cb_invitati.IsEnabled = false;
            cb_ricette.IsEnabled = false;
            lb_menuRicette.IsEnabled = false;
            tb_nomeEvento.IsEnabled = false;
            dp_dataEvento.IsEnabled = false;
            tb_closeEvent.IsEnabled = false;
            gb_listaInvitati.IsEnabled = false;
        }

        private void UpdateInterfaceEventOpen()
        {
            bt_addGuest.IsEnabled = true;
            bt_cancGuest.IsEnabled = true;
            bt_addMenu.IsEnabled = true;
            bt_cancMenu.IsEnabled = true;            
            rtb_notes.IsEnabled = true;
            dp_dataEvento.IsEnabled = true;
            cb_invitati.IsEnabled = true;
            cb_ricette.IsEnabled = true;
        }



        private void IntegerUpDown_ValueChanged_1(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (!Is_Modified(4)) bt_salva.IsEnabled = false;
            else bt_salva.IsEnabled = true;

        }

        private void Notes_sub_Click(object sender, RoutedEventArgs e)
        {
            rtb_notes.Width = notes_sub.ActualWidth;
            rtb_notes.UpdateLayout();
        }

        #endregion


    }
}
